<template>
  <div class="handle-specific-outliers">
    <a-input
      v-show="['varchar', 'text'].includes(column.desc)"
      v-model="inputValue"
      size="small"
      class="search-box"
      @pressEnter="searchOptions"
    />
    <a-popover
      v-show="['varchar', 'text'].includes(column.desc)"
      title="搜索选项"
      trigger="click"
    >
      <template slot="content">
        <a-radio-group v-model="filterType" @change="onFilterTypeChange">
          <a-radio :style="radioStyle" value="like">包含</a-radio>
          <a-radio :style="radioStyle" value="start">开始为</a-radio>
          <a-radio :style="radioStyle" value="=">精确匹配</a-radio>
          <a-radio :style="radioStyle" value="not like">不包含</a-radio>
        </a-radio-group>
      </template>
      <a-button type="default" size="small">
        ...
      </a-button>
    </a-popover>
    <div
      ref="optionsContent"
      :class="{
        content: true,
        large: !['varchar', 'text'].includes(column.desc),
      }"
      @scroll="onScrollOptions"
    >
      <div
        v-for="item in filterOptions"
        :key="item.column"
        class="options-item"
        :title="`${item.column}`"
      >
        <a-checkbox
          size="small"
          :checked="selectedValue.includes(item.column)"
          style="
            font-size: 12px;
            font-weight: 400;
            height: 16px;
            letter-spacing: 1.12px;
          "
          @change="onSelectValue($event, item.column)"
          >{{ item.column }}</a-checkbox
        >
      </div>
      <div
        v-show="filterOptions.length === 0"
        class="options-item"
        style="margin-top: 20px; text-align: center;"
      >
        暂无数据
      </div>
      <div v-if="isLoading" style="text-align: center;"><a-spin /></div>
    </div>
    <div class="replace-box replace-group">
      <span style="color: #f00;">*</span>
      <span>替换方法:</span>
      <a-select
        v-model="replaceMethod"
        :show-arrow="true"
        style="height: 24px; margin-top: 4px; width: 184px;"
        @change="emitReplaceParams"
      >
        <a-select-option
          v-for="(item, index) in methodList"
          :key="index"
          :value="item.key"
          :disabled="item.key !== 'manual'"
          >{{ item.name }}</a-select-option
        >
      </a-select>
    </div>
    <div v-if="replaceMethod === 'manual'" class="replace-box">
      <span style="color: #f00;">*</span>
      <span>将选中值替换为:</span>
      <a-input
        v-model="replaceText"
        size="small"
        placeholder="Null"
        style="font-size: 12px; height: 24px; margin-top: 4px; width: 184px;"
        @change="emitReplaceParams"
      />
    </div>
    <div class="replace-box replace-group">
      <span style="color: #f00; margin-top: 12px;">*</span>
      <span style="margin-right: 10px; margin-top: 12px;">处理结果: </span
      ><br />
      <a-radio-group v-model="resultValue" @change="emitReplaceParams">
        <a-radio class="replace-radio" :value="0">
          直接替换
        </a-radio>
        <a-radio class="replace-radio" :value="1">
          生成新字段
        </a-radio>
      </a-radio-group>
    </div>
    <div v-if="resultValue === 1" class="replace-box">
      <span style="color: #f00;">*</span>
      <span>新列名:</span>
      <a-input
        v-model="newCol"
        size="small"
        placeholder=""
        style="font-size: 12px; height: 24px; margin-top: 4px; width: 184px;"
        @change="emitReplaceParams"
      />
      <p v-if="!checkName()" class="warning-text">
        {{ columnNameErr }}
      </p>
    </div>
  </div>
</template>

<script lang="ts">
import { Vue, Component, Prop, Watch } from 'vue-property-decorator'
import { apiGetColumnStat } from '@/api/data-clean'
import { IColumn, IKeyValueStore } from '@/store/modules/dataview'
import { StatisticsAction } from '@/util/data-selection-actions'

@Component
export default class HandleSpecificOutliers extends Vue {
  @Prop() requestParams: any
  @Prop() column!: IColumn
  @Prop() editData!: any
  @Prop({ default: false }) isEdit!: boolean
  @Prop({ default: '' }) parentTableName!: boolean
  @Prop() columnList!: IColumn[]

  public methodList: any = []
  public replaceMethod: string = 'manual'
  private replaceText: string = ''
  private resultValue: number = 0
  private newCol: string = `${this.column.name}_1`
  private columnNameErr: string = ''
  private historyColName: string = ''
  private radioStyle = {
    display: 'block',
    height: '18px',
    lineHeight: '18px',
    fontSize: '12px',
    color: '#5D637E',
    letterSpacing: '1.12px',
    fontWeight: '400',
  }

  private activeKey: '=' | '<>' = '='
  private filterType: string = 'like'
  private filterTypeMapping: any = {
    '~': 'like',
    'starts with': 'start',
    '=': '=',
    '!~': 'not like',
  }
  private inputValue: string = ''
  private timer: any = null
  private currentPage: number = 1
  private totalPages: number = -1
  private isLoading: boolean = false
  private filterOptions: any[] = []
  private selectedValue: (string | null)[] = []
  mounted() {
    this.generateMetList()
    this.getFilterOptions()
  }

  public generateMetList() {
    this.methodList.push({
      name: '手动输入',
      key: 'manual',
    })
    // if (this.column.desc === 'int' || this.column.desc === 'decimal') {
    //   this.methodList.push(
    //     {
    //       name: '均值',
    //       key: 'annual',
    //     },
    //     {
    //       name: '多重插补',
    //       key: 'imputation',
    //     },
    //     {
    //       name: 'KNN插补',
    //       key: 'knn',
    //     }
    //   )
    // }
  }

  //  列名是否一致【需要去除列名空白符的比较】
  public checkName() {
    if (this.newCol.trim().length === 0 && this.resultValue === 1) {
      this.columnNameErr = '列名不能为空，请重新输入'
      return false
    }
    for (let i = 0, { length } = this.columnList; i < length; i += 1) {
      if (this.columnList[i].name === this.newCol.trim()) {
        if (this.newCol && this.newCol.trim() === this.historyColName.trim()) {
          // eslint-disable-next-line no-continue
          continue
        } else {
          this.columnNameErr = '列名已存在，请重新输入'
          return false
        }
      }
    }
    this.columnNameErr = ''
    return true
  }

  @Watch('editData', { immediate: true, deep: true })
  private onCurrentHistory(newValue: IKeyValueStore) {
    if (!newValue || !this.isEdit) {
      return
    }
    const history = newValue.data
    if (
      history.actionType === StatisticsAction.handleSpecificOutliers &&
      history.filter[0][0].col === this.column.name
    ) {
      this.activeKey = history.filter[0][0].filterType
      let selectedValue: (string | null)[] = (history.filter[0]
        .filter((item: any) => item.filterType === this.activeKey)
        .map((item: any) => item.values) as []).flat(1)
      if (selectedValue.includes('#NULL')) {
        selectedValue = selectedValue
          .filter((item) => item !== '#NULL')
          .concat(null)
      }
      this.selectedValue = selectedValue
      this.currentPage = 1
      this.getFilterOptions() // 编辑模式下选项是基于上一个表的查询，需要刷新
      this.replaceText = history.setValue
      this.replaceMethod = history.setValuePolicy
      if (history.newCol) {
        this.newCol = history.newCol
        this.historyColName = history.newCol
        this.resultValue = 1
      }
    }
  }

  private async getFilterOptions(parameters?: any) {
    /* eslint-disable unicorn/prevent-abbreviations */
    this.isLoading = true
    const requestParams = {
      ...(this.requestParams || {}),
    }
    if (this.isEdit) {
      // 编辑模式下，获取的选项是基于上一个记录的表进行查询
      requestParams.table = this.parentTableName // 编辑状态下是基于上一条记录的表名来进行筛选
    }
    const response = await apiGetColumnStat({
      data: {
        ...requestParams,
        ...parameters,
      },
    })
    this.isLoading = false
    if (!response.data.success) {
      this.$message.error(response.data.message)
      return
    }
    const { result } = response.data
    if (result) {
      this.totalPages = result.pageCount.totalPages
      if (this.currentPage > 1) {
        this.filterOptions = [...this.filterOptions, ...result.pageCount.data]
      } else {
        this.filterOptions = result.pageCount.data
      }
    } else {
      this.totalPages = 0
      this.filterOptions = []
    }
  }

  onSelectValue(event: any, value: string) {
    const { checked } = event.target
    if (checked) {
      this.selectedValue = [...this.selectedValue, value]
    } else {
      this.selectedValue = this.selectedValue.filter((item) => item !== value)
    }
    if (this.selectedValue.length > 0) {
      this.emitReplaceParams()
    } else {
      this.emitReplaceParams('reset')
    }
  }

  emitReplaceParams(type?: string) {
    if (
      type === 'reset' ||
      !this.checkName() ||
      this.selectedValue.length === 0
    ) {
      this.$emit('on-filter-params-reset')
    } else {
      this.$emit('on-filter-params-change', {
        data: {
          action: 'TRANSFORM_SET',
          transformType: 'FILTER',
          col: this.column.name,
          filter: [
            // 抛出最终用于筛选的选项值
            this.parseFilterParams(),
          ],
          description: `${
            this.resultValue === 1 ? `创建新列${this.newCol}并` : ''
          }将选中的${
            this.selectedValue.length > 1
              ? `${this.selectedValue.length}个值`
              : this.selectedValue[0]
          }替换为${this.replaceText ? this.replaceText : 'Null值'}`,
          actionType: StatisticsAction.handleSpecificOutliers, // 筛选模式下action都为FILTER，所以需要增加 actionType 辅助前端区分
          setValue: this.replaceText,
          newCol: this.resultValue === 1 ? this.newCol : '',
          setValuePolicy: this.replaceMethod,
        },
      })
    }
  }

  parseFilterParams() {
    const data = []
    if (this.selectedValue.includes(null)) {
      // 包含null值，需要分开成两段
      data.push({
        col: this.column.name,
        filterType: this.activeKey,
        values: ['#NULL'],
      })
    }
    const dataWithoutNull = this.selectedValue.filter((item) => item !== null)
    if (dataWithoutNull.length > 0) {
      data.push({
        col: this.column.name,
        filterType: this.activeKey,
        values: dataWithoutNull,
      })
    }
    return data
  }

  /**
   * 模糊搜索获取选项
   */
  searchOptions() {
    this.currentPage = 1
    const inputValue = this.inputValue.trim()
    this.getFilterOptions({
      searchFilter: [
        [
          {
            col: this.column.name,
            filterType: this.filterType === 'start' ? 'like' : this.filterType,
            values: [this.formatSearchValue(inputValue)],
          },
        ],
      ],
    })
  }

  /**
   * format成查询的格式
   */
  formatSearchValue(value: string): string {
    let formatValue = ''
    switch (this.filterType) {
      case 'start':
        formatValue = `${value}%`
        break
      case 'like':
      case 'not like':
        formatValue = `%${value}%`
        break
      case '=':
        formatValue = value
        break
      default:
        formatValue = value
    }
    return formatValue
  }

  onFilterTypeChange() {
    this.searchOptions()
  }

  toggleTabKey(tab: any) {
    this.activeKey = tab.key
    if (this.selectedValue.length > 0) {
      this.emitReplaceParams()
    }
  }

  checkIsLazyLoadOptions(): boolean {
    const { clientHeight, scrollTop, scrollHeight } = this.$refs
      .optionsContent as HTMLDivElement

    if (
      scrollTop + clientHeight + 50 > scrollHeight &&
      this.totalPages >= 0 &&
      this.currentPage < this.totalPages
    ) {
      return true
    }
    return false
  }

  /**
   * 滚动加载
   */
  onScrollOptions() {
    if (this.timer) {
      return
    }
    this.timer = setTimeout(() => {
      this.timer = null
      if (this.checkIsLazyLoadOptions()) {
        this.currentPage += 1
        const inputValue = this.inputValue.trim()
        this.getFilterOptions({
          curPage: this.currentPage,
          searchFilter: [
            [
              {
                col: this.column.name,
                filterType: () => {
                  let type = ''
                  switch (this.filterType) {
                    case 'start':
                      type = 'starts with'
                      break
                    case 'like':
                      type = '~'
                      break
                    case 'not like':
                      type = '!~'
                      break
                    default:
                      type = '='
                      break
                  }
                  return type
                },
                values: [this.formatSearchValue(inputValue)],
              },
            ],
          ],
        })
      }
    }, 300)
  }
}
</script>

<style lang="less" scoped>
.handle-specific-outliers {
  height: 100%;
  overflow: auto;

  .search-box {
    height: 24px;
    margin: 4px 0 8px;
    margin-right: 8px;
    width: 80%;
  }

  .replace-group {
    margin-top: 10px;
  }

  .replace-box {
    padding-top: 2px;

    span {
      color: #5d637e;
      font-size: 12px;
      font-weight: 400;
      height: 17px;
      letter-spacing: 0;
      line-height: 17px;
    }

    .replace-radio {
      color: #5d637e;
      font-size: 12px;
      font-weight: 400;
      height: 16px;
      line-height: 16px;
    }

    .warning-text {
      color: #e6505a;
      display: inline-block;
      margin: 0;
      word-break: break-word;
    }
  }

  .content {
    background: rgba(241, 241, 241, 0.8);
    border-radius: 2px;
    height: 89px;
    overflow-y: auto;
    width: 150px;

    &.large {
      margin-top: 8px;
    }

    &::-webkit-scrollbar {
      height: 1px;
      /*滚动条整体样式*/
      width: 6px; /*高宽分别对应横竖滚动条的尺寸*/
    }

    &::-webkit-scrollbar-thumb {
      background: #cacaca;
      /*滚动条里面小方块*/
      border-radius: 6px;
    }

    &::-webkit-scrollbar-track {
      background: #ededed;
      border-radius: 6px;
      /*滚动条里面轨道*/
    }
  }

  .options-item {
    color: #373b52;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  &::-webkit-scrollbar {
    height: 1px;
    /*滚动条整体样式*/
    width: 6px; /*高宽分别对应横竖滚动条的尺寸*/
  }

  &::-webkit-scrollbar-thumb {
    background: #cacaca;
    /*滚动条里面小方块*/
    border-radius: 6px;
  }

  &::-webkit-scrollbar-track {
    background: #ededed;
    border-radius: 6px;
    /*滚动条里面轨道*/
  }
}

/deep/ .ant-select-selection--single {
  align-content: center;
  align-items: center;
  display: flex;
  font-size: 12px;
  height: 24px;
  justify-content: flex-start;
}
</style>
